//面试笔试js题

//1、写一个方法验证emial
function checkEmail1(email){
    // var reg = new RegExp('^([\w\.])+@(\w+)([.]\w+)+$')
    var reg =/^([\w\.])+@(\w+)([.]\w+)+$/;
    return reg.test(email)
}

function checkEmail2(email){
    var reg =/^([\w\.])+@(\w+)([.]\w+)+$/;
    var resultArr = email.match(reg);
    //console.log(resultArr)
    return !!resultArr
}
console.log("1.验证email的正则方法：",checkEmail1("2293q88960@qq.com"),checkEmail2("2293q88960@qq.com"))


//2.写一份只执行一次的方法
function onceFn(fn){
    var flag = false;
    return function(){
        if(!flag){
        fn.apply(null,arguments);
        flag=true;
        };
        return undefined
    }
}
var fn = function (){console.log("我将执行一次")};
var fntest = onceFn(fn);
fntest();
fntest();
console.log("2.测试执行一次的方法：")


//3.写一个方法实现一下new实例化这个动作
 class Animal2{
     constructor(){
         this.name="parent";
     }
 }
 
var Animal = function(){
    this.name = "parent";
}
 
 function newFn(fn){
     let obj = {};
     obj.__proto__ = fn.prototype;
//     fn.apply(obj,arguments);
     fn.call(obj,arguments);
     return obj
 }
var child = newFn(Animal);
console.log("3.测试实现new的方法：",child.name)




//4.请实现一下深度拷贝
function deepClone(obj){//递归循环法
    let temp = obj instanceof Array ?[]:{};
    for(let key in obj){
        if(typeof obj[key] =="object"){
            temp[key]=deepClone(obj[key]);
        }else{
            temp[key]=obj[key];
        }
    }
    return target
}

var obj ={
    name:"deepClone--parent"
}
var target = {};//第二种方法
Object.assign(target,obj);


//第三种方法
var target = JSON.parse(JSON.stringify(obj))



//5.写一个方法实现驼峰写法
function tuoFeng(str){
    let tempArr = str.split("");
    if(tempArr[0]=="-") {
        tempArr.splice(0,1);
    }
    tempArr.forEach((item,index)=>{
        if(item == "-"){
            tempArr.splice(index,1);
            tempArr[index] = tempArr[index].toUpperCase();
        }
    })
    return tempArr.join("")
}
console.log("5.测试驼峰写法：",tuoFeng("font-size-like"));



//6.写一个字数统计法方法
function countStr(str){
    let result ={};
    for(let i of str){
        if(i in result){
             result[i]++;   
         }else{
             result[i]=1;
         }
    }
    return result
}


function countStr2(str){
    var result = {};
    for(var i=0;i<str.length;i++){
        if(str.charAt(i) in result ) {
            result[str.charAt(i)]++;
        }else{
            result[str.charAt(i)]=1;
        }
     }   
    return result
}
console.log("6.测试统计指字数的方法：",countStr("likeikk"),countStr2("heooloe"))




//7.写一个数组去除重复的方法
function qucf1(arr){
    return Array.from(new Set(arr));
}
console.log("7.去重复set方法:",qucf1([11,2,3,2,-1,-1,NaN,NaN]))

function qucf2(arr){
    let map = new Map();
    arr.forEach(item=>{
        map.set(item)
    })
    return  [...map.keys()];
}
console.log("7.去重复map方法:",qucf2([1,3,3,2,-1,-1,NaN,NaN]))


function qucf3(arr){
    var res=[];
    var flag=true;
    arr.forEach((item,index)=>{
        if(item != item){
            flag && res.indexOf(item)== -1 ? res.push(item):"";
            flag = false;
        }else{
            res.indexOf(item)<0 ? res.push(item):"";
        }
    })
    return res
}
console.log("7.去重复indexof方法:",qucf3([11,2,3,2,-1,-1,NaN,NaN]))

//8.写一个方法获取数组中的最大/小值
function maxNum(arr){
    var max = arr[0];
    for(var i=0;i<arr.length;i++){
        if(arr[i]>max) {
            max =arr[i]
        }
    }
    return max
}


function absMaxNum(arr){
    var max =Math.abs( arr[0]);
    for(var i=0;i<arr.length;i++){
        if(Math.abs(arr[i])>max) {
            max =arr[i]
        }
    }
    return max
}

console.log("8.获取数组中的最大值：",maxNum([1,-98,998,-76,-999]), absMaxNum([1,-98,998,-76,97667,-999,-9878]))



//9.写一个方法实现改变this指向到目标
function bindThis(fn,obj){
    return fn.bind(obj)
}

function bindThis2(fn,obj){
    return function(){
        return fn.apply(obj,arguments);
    }
}


//10.获取最近一个父亲节点
function getPreNode(node1,node2){
    if(node1.contains(node2)){
     return node1
    }else if(node2.contains(node1)){
        return node2
    }else{
        return getPreNode(node1.parentNode,node2)
    }
}


//11.请问以下代码输出的结果是什么
 function foo(){
     try{
         var n=50;
         throw "";
         }catch(e){
            console.log(n);
            n=450;         
     }
 }

foo();




//12.写一个方法实现：add(1,2,3)=6;add(1)(2)(3)=6;add(1,2)(3)=6;
function add(...a){
    var res =0;
    //a.forEach(item=>{
    //    res=Number(item)+res;
    //});
    //a=res;
    a= a.reduce((pre,nex)=>{
        return pre+nex
    },0)
    function sum(b){
        a=a+b;
        return sum
    }
    sum.toString= function(){
        return a
    };
    return sum
}

console.log("12.测试add方法：",add(1)(2)(3),add(1,2,3),add(1,2)(3))




//13.写一个方法实现数字加千位分隔符
//100,000,23
function moneyFormat(numStr){
    let xiaoshu = numStr.split(".")[1] || "";
    let zhengshu = numStr.split(".")[0].split("").reverse();
    let tempArr=[];
    for(var i =0;i<zhengshu.length;i++){
        tempArr.push(zhengshu[i]);
        if(i%3==2 && i <zhengshu.length){
            tempArr.push(",")
        }
    }
    if(!xiaoshu==""){
        Exiaoshu = "."+xiaoshu;
    }else{
        Exiaoshu=""
    }
    var Ezhengshu = tempArr.reverse().join("");
    return Ezhengshu+Exiaoshu


}
console.log("13.测试金额加千位分隔符号的方法：", moneyFormat("1000034"))



//14.实现一下数组排序

//sort方法实现
var arr =[1,22,1,55,-8.32,0];
function sortFn(arr){
    arr.sort(function(a,b){
        return a-b
    });
    return arr
}
console.log("14.测试sortFn方法：",sortFn(arr))


//冒泡排序方法
function bubbleSort(arr){
    for(var i =arr.length-1;i>=0;i--){
        for(var j=0;j<i;j++){
            if(arr[j]>arr[j+1]){
                let temp = arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp
            }
        }
    }
    return arr
}

console.log("14.测试bubbleSort方法：",bubbleSort(arr))

//选择排序
function selectSort(arr){
    for(var i =0;i<arr.length;i++){
        var min = i;
        for(var j=min+1;j<arr.length;j++){
            if(arr[min]>arr[j]){
                min = j
            }
           
        }
        var temp = arr[min];
            arr[min] = arr[j];
            arr[j] = temp;
    }
    return arr
}



//插入排序
function insertSort(arr){
    for(var i=1;i<arr.length;i++){
        var temp = arr[i];
        var j=i;
        while(arr[j-1]>temp && j>0){
            arr[j]=arr[j-1];
            j--;
        }
        arr[j]=temp
    }
    return arr
}

//15.实现一个休眠函数实现第一秒打印1，第二秒打印2.。。
//方法一：
async function sleep(delay=1000){
    return new Promise(resolve=>{
        setTimeout(function(){
            resolve();
        },delay)
    })
}
async function write(){
    for(item of [1,2,3]){
        await sleep();
        console.log(item)
    }
}

//方法二：
for(let i=0;i<4;i++){
    setTimeout(()=>{
        console.log(i)
    },i*1000)
}

//方法三
for(var i=0;i<4;i++){
    (function(i){
        setTimeout(function(){
        console.log(i)
    },i*1000)
    })(i)
}

//方法四
function fn1(lists){
    let promise =Promise.resolve();
    lists.map(item=>{
         promise = promise.then(res=>{
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    console.log(item);
                    resolve()
                },1000)
            })
        })
    })
}

//方法五
function fn2(lists){
    lists.reduce((pre,nex)=>{
        return pre.then(res=>{
            return new Promise((resolve,reject)=>{
                setTimeout(()=>{
                    console.log(nex);
                    resolve();
                },1000)
            })
        })
    },Promise.resolve())
}


//16.实现一个格式化日期的方法
function DateFormat(date,format="XXXX年MM月DD日 hh:mm:ss 周Day"){
    var config={
        XXXX:date.getFullYear(),
        MM:date.getMonth()+1,
        DD:date.getDate(),
        hh:date.getHours(),
        mm:date.getMinutes(),
        ss:date.getSeconds(),
        Day:date.getDay()==0?7:date.getDay(),
    }
    for(let item in config){
        format=format.replace(item,config[item])
    }
    return format
 }
 var date = new Date("2020-3-8 12:23:45")
 console.log("16.测试dateformat方法：",date,DateFormat(date))



 // 17. 用apply或则call实现bind
function mybind(obj,args){
     args = Array.prototype.slice.call(arguments,1);
    let context = this;
    return function (newargs){
        args = args.concat(Array.prototype.slice.call(newargs));
        return context.apply(obj,args)
    }
}


// 18. 用setTimeout实现setInterval
function myInterval(fn,delay=1000){
    setTimeout(function(){
        fn();
        myInterval(fn,delay=1000);
    },delay)
}
// myInterval(function(){
//     console.log("自己实现的myInterval方法")
// },2000)

// 19. 写一个计算器方法
function jisuan(num1,num2,icon){
    switch(icon){
        case "+": return Number(num1) + Number(num2);
        break;
        case "-":return Number(num1) - Number(num2);
        break;
        case "*":return Number(num1) * Number(num2);
        break;
        case "/":return Number(num1) / Number(num2);
        break;
        case "%":return Number(num1) % Number(num2);
        break;
        default:console.log("输入符号错误！")
    }
}
console.log("19.测试计算器方法：",jisuan(9,99,"-") )





// 20. 写一个方法实现promise.all接口
function promiseAll(arr){
    return new Promise((resolve,reject)=>{
        if(arr instanceof Array == false){
            return reject(new TypeError("参数必须数组形式"))
        };
        var count =0;
        let proNum = arr.length;
        let result = new Array(proNum);
        arr.forEach((item,index)=>{
            (function (index){
                Promise.resolve().then(res=>{
                count++;
                result[index] = res;
                if(count==proNum){
                    return resolve(result);
                }
            },err=>{
                return reject(err)
            })

            })(index)
            
        })
    })
};


// 21. 写一个方法实现延时提示
function delayFn(){
    let arr =[new Promise(resolve=>{
        setTimeout(_=>{
            resolve("请求成功啦！")
        },5000)
    }),new Promise((resolve,reject)=>{
        setTimeout(_=>{
            reject("请求超时啦")
        },1000)
    })]
    return Promise.race(arr)
}
delayFn().then(res=>{
    console.log("成功啦--》",res)
},err=>{
     console.log("失败啦--》",err)
})



// 22.  实现一个请求缓存方法
function cacheFn(name){
    var cache = cacheFn.cache || (cacheFn.cache = new Map());
    if(cache.has(name)){
        return Promise.resolve(cache.get(name))
    }else{
        return ajax(`http://adsaca${name}`).then(res=>{
            return res
        })
    }

}


// 23. 用promise封装一个ajax
function ajax(url){
    return new Promise((resolve,reject)=>{
        let xhr = new XMLHttpRequest();
        xhr.open("get",url);
        xhr.send();
        xhr.onload=function(){
            if(xhr.status=200 && xhr.readyState==4){
                return resolve(xhr.responseText)
            }
        };
        xhr.onerror=function(err){
            return reject(err)
        }
    })
}





